﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Radiation.Common
{
    public class Configuration
    {
        // Static part

        public static Configuration _instance;

        public static void Init()
        {
            _instance = new Configuration();
        }

        public static Configuration Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Configuration();
                return _instance;
            }
        }

        // Dynamic part

        readonly string _config_file = "config.cfg";
        string _choosen_config_file = "";
        string[][] _parsed_config;
        int _used_config_slots = 0;

        public Configuration(string config_file = "")
        {
            _parsed_config = new string[10][];
            _choosen_config_file = config_file;
            ParseConfiguration();
        }

        public string this[string param_name]
        {
            get
            {
                for (int i = 0; i < _used_config_slots; i++)
                    if (_parsed_config[i][0] == param_name)
                        return _parsed_config[i][1];
                return "";
            }
            set
            {
                for (int i = 0; i < _used_config_slots; i++)
                    if (_parsed_config[i][0] == param_name)
                        _parsed_config[i][1] = value;
            }
        }

        public bool ParameterExists(string name)
        {
            for (int i = 0; i < _used_config_slots; i++)
                if (_parsed_config[i][0] == name)
                    return true;
            return false;
        }

        public string[] this[int param_index]
        {
            get
            {
                if (param_index >= 0 && param_index < _used_config_slots)
                    return _parsed_config[param_index];
                return null;
            }
        }

        public int ParamCount
        {
            get
            {
                return _used_config_slots;
            }
        }

        public void ParseConfiguration()
        {
            if ((_choosen_config_file != null && File.Exists(_choosen_config_file)) || File.Exists(_config_file))
            {
                StreamReader sr;
                if (_choosen_config_file.Length > 0)
                    sr = new StreamReader(_choosen_config_file, Encoding.ASCII);
                else
                    sr = new StreamReader(_config_file, Encoding.ASCII);

                string temp_config_string = "";
                int line = 0;

                while (true)
                {
                    temp_config_string = sr.ReadLine();
                    if (temp_config_string == null)
                    {
                        sr.Close();
                        break;
                    }
                    else
                    {
                        if (temp_config_string.Length > 0 && temp_config_string[0].ToString() != "#")
                        {
                            string var_name = "";
                            string var_value = "";

                            bool name_passed = false;
                            bool inside_name = false;
                            bool inside_value = false;
                            bool equal_passed = false;
                            bool end_of_line_ok = false;

                            for (int i = 0; i < temp_config_string.Length; i++)
                            {
                                if (equal_passed)
                                {
                                    if (inside_value)
                                    {
                                        if (temp_config_string[i].ToString() == ";" &&
                                            temp_config_string[i - 1].ToString() != "\\" &&
                                            temp_config_string[i - 2].ToString() != "\\")
                                        {
                                            end_of_line_ok = true;
                                            break;
                                        }
                                        else
                                        {
                                            if (temp_config_string[i].ToString() == ";")
                                                var_value = var_value.Substring(0, var_value.Length - 2); // delete the two "\" 
                                            var_value += temp_config_string[i].ToString();
                                        }
                                    }
                                    else
                                    {
                                        if (temp_config_string[i].ToString() != " ")
                                        {
                                            var_value += temp_config_string[i].ToString();
                                            inside_value = true;
                                        }
                                    }
                                }
                                else
                                {
                                    if (name_passed)
                                    {
                                        if (temp_config_string[i].ToString() == "=")
                                            equal_passed = true;
                                    }
                                    else
                                    {
                                        if (inside_name)
                                        {
                                            if (temp_config_string[i].ToString() == " ")
                                                name_passed = true;
                                            else
                                                var_name += temp_config_string[i].ToString();
                                        }
                                        else
                                        {
                                            if (temp_config_string[i].ToString() != " ")
                                            {
                                                var_name += temp_config_string[i].ToString();
                                                inside_name = true;
                                            }
                                        }
                                    }
                                }
                            }// end of for

                            if (!end_of_line_ok)
                                Logger.Instance["error"].add("[fatal] Parsing error : \";\" excepeted (line:" + line.ToString() + "|"+temp_config_string+")"/*+var_name+"|"+var_value*/);
                            else
                                AddConfigSlot(var_name, var_value);
                        }
                    }

                    line++;
                }
            }
            else
                Logger.Instance["error"].add("[fatal] Unable to open config file");
        }

        public void CreateParameter(string name, string value)
        {
            AddConfigSlot(name, value);
        }

        private void AddConfigSlot(string name, string value)
        {
            bool found = false;
            int found_index = 0;

            for (int i = 0; i < _used_config_slots; i++)
                if (_parsed_config[i][0] == name)
                {
                    found = true;
                    found_index = i;
                    break;
                }

            if (!found)
            {
                if (_used_config_slots >= _parsed_config.Length)
                {
                    string[][] temp = new string[_parsed_config.Length + 10][];
                    for (int i = 0; i < _used_config_slots; i++)
                        temp[i] = _parsed_config[i];
                    _parsed_config = temp;
                }

                _parsed_config[_used_config_slots] = new string[2] { name, value };
                _used_config_slots++;
            }
            else
            {
                _parsed_config[found_index][1] = value;
            }
        }
    }
}
